using System.Diagnostics;
using System.Collections;
using System.Configuration;
using System.Globalization;
using System.Text;
using System.Web;
using System.Web.Configuration;

using AddonNice.Settings;
using AddonNice.RewriteRules.Tools;
using Rewrite.NET;

namespace AddonNice.RewriteRules
{
    /// <summary>
	/// Default Rule
	/// This Class is responsible for Splitting up Addon Nice urls into real urls for the AddonNice Portal
	/// </summary>
	public class DefaultRule : IRules
	{
		public	bool BreakAfter
		{
			get
			{
				return Section.BreakOnAfter;
			}
            set {}
	    }

		public	bool BreakOnFirst
		{
			get
			{
				return Section.BreakOnFirst;
			}
            set {}
	    }

		IndexRule _Section	=	null;
		public IndexRule Section
		{
			get
			{
				return _Section;
			}
			set
			{
				_Section	=	value;
			}
		}
		
		public bool Execute(HttpApplication Appl,ref string Path)
        {
		    if ( RewriteTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DefaultRule Execute BEG BreakOnFirst: {0}, BreakAfter: {1}, Path: '{2}', Url: '{3}'",
                    new object[]{BreakOnFirst,BreakAfter,Path,Appl.Request.Url}),RewriteTraceSwitch.Sw.Info);
			string _handlerFlag		        =	"portal";
			string _defaultSplitter         =	"__";
			bool _pageidNoSplitter	        =	false;
			// collect settings
			string ob1				        =	Section.HandlerFlag;
			if ( !string.IsNullOrEmpty(ob1))
			{
				_handlerFlag		        =   ob1.ToLower(CultureInfo.InvariantCulture);
			}
			
			ob1						        =	Section.HandlerSplitter;
			if ( !string.IsNullOrEmpty(ob1))
			{
				_defaultSplitter	        =	ob1;
			}
			else
			{
                _defaultSplitter            =   Config.HandlerDefaultSplitter;
			}

			_pageidNoSplitter		        =	Section.PageIdNoSplitter;
			if ( RewriteTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DefaultRule _handlerFlag: {0}, _defaultSplitter: {1}, _pageidNoSplitter: {2}", _handlerFlag,_defaultSplitter,_pageidNoSplitter),RewriteTraceSwitch.Sw.Info);

			// determine if the user is navigating to a url to be handled
			string _startpath               =   (Engine.ApplicationPath(Appl).ToLower(CultureInfo.InvariantCulture) + "/" + _handlerFlag + "/");
			string _path			        =   Path;

			if ( RewriteTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DefaultRule Path: '{0}', _startpath: '{1}'", Path,_startpath),RewriteTraceSwitch.Sw.Info);
            if (!_path.ToLower(CultureInfo.InvariantCulture).StartsWith(_startpath))
            {
                if (RewriteTraceSwitch.Sw.TraceVerbose)
                    Trace.WriteLine("[V]DefaultRule Execute END no match", RewriteTraceSwitch.Sw.Info);
                return false;
            }
            //Remove start tag...
            _path			                =   _path.Substring(_startpath.Length);
            //split the path into components
            string[] parts	                =   _path.Split(new char[]{'/'},System.StringSplitOptions.RemoveEmptyEntries);
            int nbparts                     =   parts.GetUpperBound(0)+1;
            string nextparts                =   string.Empty;
            string pageName                 =   General.DefaultPage;
			if ( RewriteTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DefaultRule nbparts: {0}", nbparts),RewriteTraceSwitch.Sw.Info);
            if ( nbparts > 0 )
            {
                string lastPart             =   parts[nbparts-1];
                pageName                    =   parts[nbparts - 1];
                int idx                     =   lastPart.IndexOf('?');
				if ( RewriteTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DefaultRule lastPart: {0}, idx: {1}", lastPart,idx),RewriteTraceSwitch.Sw.Info);
                // query strings have been detected
                if (idx != -1)
                {
                    nextparts               =   lastPart.Substring(idx+1);
                    parts[nbparts - 1]      =   lastPart.Substring(0, idx);
                    pageName                =   parts[nbparts - 1];
                    // remove duplicate keys
                    string[] parts2         =   nextparts.Split('&');
                    int nb2                 =   parts2.GetUpperBound(0)+1;
                    int k                   =   nbparts;
                    for (int j = 0; j < nb2; j++)
                    {
                        bool found          =   false;
                        if (parts2[j] == string.Empty)
                            continue;
                        string[] key2       =   parts2[j].Split('=');
                        for (int i = 0; !found && i < nbparts; i++)
                        {
							string str      =   parts[i].Replace(_defaultSplitter, "=");
							string[] key    =   str.Split('=');
                            if ((key.GetUpperBound(0) == key2.GetUpperBound(0)) 
                                && (key[0].Trim().ToLower(CultureInfo.InstalledUICulture) == key2[0].Trim().ToLower(CultureInfo.InstalledUICulture)))
                            {
								if ( RewriteTraceSwitch.Sw.TraceVerbose )
                                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DefaultRule replacing '{0}' by '{1}'", parts[i],parts2[j]),RewriteTraceSwitch.Sw.Info);
                                // we replace old version by new
                                parts[i]    =	parts2[j].Replace("=",_defaultSplitter);
                                // we mark new value as seen
                                parts2[j]   =	string.Empty;
                                found       =	true;
                            }
                        }
                        if (!found)
                            k++;
                    }
                    // adding new values and inverting arrays
                    // we must take care to keep pageID in nbpart-1 position (Cf Splitter)
                    if ( k != 0 )
                    {
                        string[] parts3     =   new string[k];
                        int l               =   nbparts-2;
						for (int i = 0; i < l; i++)
						{
							parts3[i]       =   parts[i];
							if ( RewriteTraceSwitch.Sw.TraceVerbose )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DefaultRule adding i={0} part:{1}'",i, parts3[i]),RewriteTraceSwitch.Sw.Info);
						}

                        for (int i = 0; i < nb2; i++)
                            if ( parts2[i] != string.Empty )
							{
                                parts3[l++] =   parts2[i];
								if ( RewriteTraceSwitch.Sw.TraceVerbose )
                                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DefaultRule adding i={0} part:{1}'",l-1, parts3[l-1]),RewriteTraceSwitch.Sw.Info);
								}
						//last 2 parts: pageid and pagename
						for (int i = nbparts - 2; i < nbparts; i++)
						{
							parts3[l++]     =   parts[i];
							if ( RewriteTraceSwitch.Sw.TraceVerbose )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DefaultRule adding i={0} part:{1}'", l-1, parts3[l-1]),RewriteTraceSwitch.Sw.Info);
						}

                        parts               =   parts3;
                    }
                }
            }

            StringBuilder sb0               =   new StringBuilder(Engine.ApplicationPath(Appl));
            StringBuilder sb                =   new StringBuilder();
            string PageLoc                  =   string.Empty;
            string UrlName                  =   string.Empty;
			General.PageType secure         =   General.Splitter(parts, sb,_defaultSplitter,_pageidNoSplitter,ref PageLoc,ref UrlName);
            string strRet                   =   string.Empty;
            switch ( secure )
            {
                default:
                    if (UrlName == string.Empty )
                        UrlName                     =   General.DefaultPage;
                    if ( PageLoc == string.Empty )
                            sb0.AppendFormat("/{0}",UrlName);
                    else    sb0.AppendFormat("/{0}/{1}",PageLoc,UrlName);
                break;
                case General.PageType.Special:
                    if ( PageLoc == string.Empty )
                            sb0.AppendFormat("/{0}",pageName);
                    else    sb0.AppendFormat("/{0}/{1}",PageLoc,pageName);
                break;
                case General.PageType.Register:
                    sb0.Append(General.DefaultRegisterPage(PageLoc,UrlName));
                break;
                case General.PageType.EditProfile:
                    sb0.Append(General.DefaultEditProfilePage(PageLoc,UrlName));
                break;
                case General.PageType.Logon:
                    sb0.Append(General.DefaultLogonPage(PageLoc,UrlName));
                break;
                case General.PageType.Logoff:
                    sb0.Append(General.DefaultLogoffPage(PageLoc,UrlName));
                break;
                case General.PageType.ChangePwd:
                    sb0.Append(General.DefaultChangePwdPage(PageLoc,UrlName));
                break;
                case General.PageType.RecoverPwd:
                    sb0.Append(General.DefaultRecoverPwdPage(PageLoc,UrlName));
                break;
            }
            sb0.Append(sb.ToString());
            strRet                          =   sb0.ToString();
            if ( RewriteTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DefaultRule Execute END changed Path: '{0}'", strRet),RewriteTraceSwitch.Sw.Info);
            Path                            =   strRet;
            return true;
        }
    }
}
